/**
 * Copyright (c) 2009 Mujtaba Hassanpur.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

import java.awt.*;
import java.awt.geom.*;

/**
 * Represents a brick with a position (x,y) and a color.
 */
public class Brick implements Drawable
{
	// A brick is a square; this value represents the width in the world
	// coordinate system.
	public static final int BRICK_SIZE = 32;
	public static final int BEVEL_WIDTH = BRICK_SIZE / 16;
	
	// This position represents the coordinates within the board grid, not the
	// world map.
	protected int positionX, positionY;
	protected Color color;
	
	/**
	 * Default constructor. Creates a white brick at (0,0).
	 */
	public Brick()
	{
		positionX = 0;
		positionY = 0;
		color = Color.white;
	}
	
	/**
	 * Creates a white brick at (x,y).
	 * 
	 * @param x The x-position of the brick on the map. Must be >= 0.
	 * @param y The y-position of the brick on the map. Must be >= 0.
	 */
	public Brick(int x, int y)
	{
		this();
		if(x >= 0)
			positionX = x;
		if(y >= 0)
			positionY = y;
	}
	
	/**
	 * Creates a brick of the specified color at (x,y).
	 * 
	 * @param x The x-position of the brick on the map. Must be >= 0.
	 * @param y The y-position of the brick on the map. Must be >= 0.
	 * @param initColor The color of the brick.
	 */
	public Brick(int x, int y, Color initColor)
	{
		this(x, y);
		color = initColor;
	}
	
	/**
	 * Gets the x-position of the brick on the map.
	 * 
	 * @return Returns the x-position of the brick on the map.
	 */
	public int getPositionX()
	{
		return positionX;
	}
	
	/**
	 * Gets the y-position of the brick on the map.
	 * 
	 * @return Returns the y-position of the brick on the map.
	 */
	public int getPositionY()
	{
		return positionY;
	}
	
	/**
	 * Gets the color of the brick.
	 * 
	 * @return Returns the color of the brick.
	 */
	public Color getColor()
	{
		return color;
	}
	
	/**
	 * Sets the x-position of the brick on the map, where x >= 0.
	 * 
	 * @param x The x-position of the brick on the map; must be >= 0.
	 * @return Returns true if successful, otherwise false.
	 */
	public boolean setPositionX(int x)
	{
		boolean result = false;
		
		if(x >= 0)
		{
			positionX = x;
			result = true;
		}
		
		return result;
	}
	
	/**
	 * Sets the y-position of the brick on the map, where y >= 0.
	 * 
	 * @param y The y-position of the brick on the map; must be >= 0.
	 * @return Returns true if successful, otherwise false.
	 */
	public boolean setPositionY(int y)
	{
		boolean result = false;
		
		if(y >= 0)
		{
			positionY = y;
			result = true;
		}
		
		return result;
	}
	
	public void draw(Graphics2D g)
	{
		// save
		AffineTransform saveAT = g.getTransform();
		Color saveColor = g.getColor();
		
		// draw
		g.setColor(color);
		g.fillRect(getWorldPositionX(), getWorldPositionY(), BRICK_SIZE, BRICK_SIZE);
		g.setColor(getDarkerColor(color));
		g.fillRect(getWorldPositionX(), getWorldPositionY(), BRICK_SIZE, BEVEL_WIDTH);
		g.fillRect(getWorldPositionX() + BRICK_SIZE - BEVEL_WIDTH, getWorldPositionY(), BEVEL_WIDTH, BRICK_SIZE);
		g.setColor(getLighterColor(color));
		g.fillRect(getWorldPositionX(), getWorldPositionY(), BEVEL_WIDTH, BRICK_SIZE);
		g.fillRect(getWorldPositionX(), getWorldPositionY() + BRICK_SIZE - BEVEL_WIDTH, BRICK_SIZE, BEVEL_WIDTH);
		
		// restore
		g.setTransform(saveAT);
		g.setColor(saveColor);
	}
	
	/**
	 * Given a color, create a lighter version of the color.
	 * @param inColor Reference color.
	 * @return Returns a color that is lighter than the reference color.
	 */
	private Color getLighterColor(Color inColor)
	{
		int r = inColor.getRed() + 96;
		int g = inColor.getGreen() + 96;
		int b = inColor.getBlue() + 96;
		
		if(r > 255) r = 255;
		if(g > 255) g = 255;
		if(b > 255) b = 255;
		
		return new Color(r, g, b);
	}
	
	/**
	 * Given a color, create a darker version of the color.
	 * @param inColor Reference color.
	 * @return Returns a color that is darker than the reference color.
	 */
	private Color getDarkerColor(Color inColor)
	{
		int r = inColor.getRed() - 96;
		int g = inColor.getGreen() - 96;
		int b = inColor.getBlue() - 96;
		
		if(r < 0) r = 0;
		if(g < 0) g = 0;
		if(b < 0) b = 0;
		
		return new Color(r, g, b);
	}
	
	public int getWorldPositionX()
	{
		return (positionX * BRICK_SIZE);
	}
	
	public int getWorldPositionY()
	{
		return (positionY * BRICK_SIZE);
	}
}
